home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
PROGENV
/
Inspector.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-26
|
13KB
|
569 lines
#ifdef __GNUG__
#pragma implementation
#endif
#include "ET++.h"
#include "Inspector.h"
#include "ObjList.h"
#include "OrdColl.h"
#include "Dictionary.h"
#include "ObjectTable.h"
#include "ClassItem.h"
#include "ClassManager.h"
#include "AccessMem.h"
#include "MenuBar.h"
#include "WindowSystem.h"
#include "Buttons.h"
#include "Filler.h"
#include "Math.h"
#include "Fields.h"
#include "ObjectView.h"
#include "Reference.h"
#include "InspItem.h"
#include "ClassList.h"
#include "EtPeManager.h"
#include "EtPeCmdNo.h"
#include "EtProgEnv.h"
const int cMaxObjects= 400;
//---- timeout handler to refresh inspector views ------------------------------
class PeRefreshHandler : public SysEvtHandler {
PeInspector *inspector;
public:
MetaDef(PeRefreshHandler);
PeRefreshHandler(PeInspector *w) : SysEvtHandler(0)
{ inspector= w; }
bool HasInterest(SysEventCodes)
{ return inspector->IsOpen(); }
void Notify(SysEventCodes, int)
{ inspector->GetWindow()->UpdateEvent(); }
};
NewMetaImpl(PeRefreshHandler, SysEvtHandler, (TP(inspector)));
//---- update References to deleted objects
void InspectorFreeHook(void*, void *addr, size_t sz)
{
void *end= (void*)((u_long)addr + sz);
for (int i= 0; i < PeInspector::allInspectors->Size(); i++) {
PeInspector *ip= (PeInspector*)PeInspector::allInspectors->At(i);
if (addr != ip)
ip->FreedMemory(addr, end);
}
}
//---- FindInspReferences --------------------------------------------------------------
class PeFindInspReferences: public AccessObjPtrs {
protected:
Object *referencesTo;
PeInspector *ip;
public:
PeFindInspReferences(PeInspector *insp) : AccessObjPtrs(0)
{ ip= insp; }
void ReferencesTo(Object *op)
{ referencesTo= op; }
void FoundPointer(Object*, char*, int, bool);
};
void PeFindInspReferences::FoundPointer(Object *op, char *name, int at, bool)
{
if (op == referencesTo /* && ?? !inObject->IsKindOf(Assoc) */
&& !inObject->IsKindOf(PeObjectItem))
ip->FoundReference(inObject, name, at);
}
//---- Inspector ----------------------------------------------------------------
NewMetaImpl(PeInspector, EtPeTool, (TP(classes), TP(objects), TP(classItems), TP(objectItems),
TP(references), TP(referenceItems), TP(refTitle), TP(objTitle)));
PeInspector *PeInspector::inspector;
int PeInspector::inspcnt;
OrdCollection *PeInspector::allInspectors;
PeInspector::PeInspector(Manager *m) : EtPeTool(m, "Inspector")
{
}
PeInspector::~PeInspector()
{
allInspectors->RemovePtr(this);
if (allInspectors->Size() == 0) {
Storage::SetFreeHook(0, 0);
SafeDelete(allInspectors);
}
if (refresh) {
refresh->Remove();
refresh= 0;
}
SafeDelete(objView);
SafeDelete(findReferences);
SafeDelete(classes);
SafeDelete(objects);
SafeDelete(references);
//SafeDelete(refTitle);
if (path) {
path->FreeAll();
SafeDelete(path);
}
//SafeDelete(objTitle);
}
VObject *PeInspector::DoMakeContent()
{
findReferences= new PeFindInspReferences(this);
classes= new PeClassListView(this, TRUE);
objTitle= new TextField(cIdNone, 20, gFixedFont->WithFace(eFaceItalic));
objTitle->SetEditable(FALSE);
objects= new CollectionView(this, 0, eCVDefault);
objects->SetMinExtent(Point(400, 0));
ResetObjects();
objects->SetId(cIdObjects);
refTitle= new TextField(cIdNone, 20, gFixedFont->WithFace(eFaceItalic));
refTitle->SetEditable(FALSE);
references= new CollectionView(this, 0, eCVDefault, 0);
references->SetMinExtent(Point(400, 0));
ResetReferences();
references->SetId(cIdReferences);
objView= new PeObjectView();
objView->SetNextHandler(this);
SetFirstHandler(objView);
VObject *classScroller= new Scroller(classes, Point(-1, 100));
classScroller->SetFlag(eVObjHFixed | eVObjVFixed);
AddKeySelectItem(classScroller);
VObject *w=
new VExpander(gPoint2,
new HBox(gPoint2, (VObjAlign)(eVObjVEqual|eVObjHExpand),
classScroller,
new VExpander(gPoint2,
objTitle,
new Scroller(objects, gPoint0, cIdNone, eScrollRight),
0
),
new VExpander(gPoint2,
refTitle,
new Scroller(references, gPoint0, cIdNone, eScrollRight),
0
),
0
),
new HExpander(gPoint8,
start= new ActionButton(cIdShiftStart, "||<"),
left= new ActionButton(cIdShiftLeft, "<<"),
new ActionButton(cIdShiftAppl, "Appl"),
right= new ActionButton(cIdShiftRight, ">>"),
end= new ActionButton(cIdShiftEnd, ">||"),
0
),
new HExpander(gPoint2, new Scroller(objView, Point(550, 300)), 0),
0
);
path= new OrdCollection;
if (allInspectors == 0) {
allInspectors= new OrdCollection;
Storage::SetFreeHook(InspectorFreeHook, 0);
}
allInspectors->Add(this);
UpdateButtons();
position= -1;
gSystem->AddTimeoutHandler(refresh= new PeRefreshHandler(this));
return w;
}
MenuBar *PeInspector::DoMakeMenuBar()
{
MenuBar *mb= EtPeTool::DoMakeMenuBar();
Menu *m= new Menu("Classes");
m->AppendItems( "Update List", cUPDATELIST,
"Hide Empty", cEMPTYCLASSES,
"Edit Definition", cEDITDECL,
"Edit Implementation", cEDITIMPL,
0);
mb->AddMenu(m);
m= new Menu("Objects");
m->AppendItems( "All Instances", cSHOWALL,
"References", cOBJREFERENCES,
"Object View", cABSTRVIEW,
"Object Structure", cOBJBROWSER,
0);
mb->AddMenu(m);
return mb;
}
void PeInspector::Init(Object *op)
{
Push(new Ref(*op));
}
void PeInspector::MoveTo(int pos)
{
pos= Math::Range(0, path->Size() - 1, pos);
if (pos == position)
return;
position= pos;
Ref *r= (Ref*)path->At(position);
objView->SetInspected(r);
ShowReference(r);
UpdateButtons();
}
void PeInspector::Push(Ref *r)
{
if (position != path->Size() - 1)
while(path->Size() > position+1) {
Object *tmp= path->RemoveLast();
if (tmp)
delete tmp;
}
int i= path->IndexOf(r);
if (i < 0)
path->Add(new Ref(*r));
else {
while(path->Size() > i+1) {
Object *tmp= path->RemoveLast();
if (tmp)
delete tmp;
}
}
objView->SetInspected(r);
ShowReference(r);
position= path->Size() - 1;
UpdateButtons();
}
void PeInspector::ShowReference(Ref *ref)
{
Class *cl= 0;
Object *op;
if (op= ref->GetObject())
cl= op->IsA();
else {
Reset();
return;
}
ShowClass(cl);
ShowObject((Object*)ref->GetBase());
}
void PeInspector::ShowClass(Class *cl)
{
if (classes->SelectClass(cl))
LoadObjectsOfClass(cl, TRUE);
}
void PeInspector::ShowObject(Object *op)
{
PeObjectItem *oi;
Iter next(objectItems);
for (int i= 0; oi= (PeObjectItem*)next(); i++) {
if (oi->GetObject() == (Object*)op) {
SelectAndRevealItem(objects, i);
return;
}
}
objects->ClearSelection();
}
void PeInspector::SelectAndRevealItem(CollectionView *cv, int at)
{
Rectangle sr(0, at, 1, 1);
cv->SetSelection(sr);
Rectangle r(cv->ItemRect(sr));
//r.extent.x= 1; // reveal left most pixels
//cv->RevealRect(r, r.extent);
cv->RevealAlign(r);
}
void PeInspector::UpdateButtons()
{
start->Enable(position != 0);
left->Enable(position != 0);
bool b= position == path->Size() - 1;
right->Enable(!b);
end->Enable(!b);
}
void PeInspector::LoadObjectsOfClass(Class *cl, bool members)
{
int i;
objectItems= new ObjList;
{
Object *op;
ObjectTableIter next(cl, members);
for (i= 0; op= next(); i++) {
objectItems->Add(new PeObjectItem(cIdNone, op));
if (i == cMaxObjects) {
VObject *vop= new TextItem("...", gFixedFont->WithFace(eFaceItalic));
vop->Disable();
objectItems->Add(vop);
break;
}
}
}
objTitle->SetFString(TRUE, "%d instance%s", i, (i > 1) ? "s" : "");
objects->SetCollection(objectItems, TRUE);
objects->Update();
}
void PeInspector::Control(int id, int what, void *data)
{
PeObjectItem *oi;
Rectangle r;
switch (id) {
case cIdShiftAppl:
Push(new Ref(*gApplication));
break;
case cIdShiftLeft:
MoveTo(position-1);
break;
case cIdShiftRight:
MoveTo(position+1);
break;
case cIdShiftStart:
MoveTo(0);
break;
case cIdShiftEnd:
MoveTo(path->Size()-1);
break;
case cIdObjects:
r= objects->GetSelection();
if (r.IsEmpty())
return;
oi= (PeObjectItem*) objectItems->At(r.origin.y);
if (oi == 0 || !oi->IsKindOf(PeObjectItem))
return;
DoInspect(oi->GetObject());
references->ClearSelection();
break;
case cIdReferences:
r= references->GetSelection();
if (r.IsEmpty())
return;
oi= (PeObjectItem*) referenceItems->At(r.origin.y);
if (oi == 0 || !oi->IsKindOf(PeObjectItem))
return;
DoInspect(oi->GetObject());
break;
default:
switch(what) {
case cPeCLChangedClass:
LoadObjectsOfClass((Class*)data, TRUE);
references->ClearSelection();
break;
case cPeLoadRef:
Push((Ref*)data);
break;
case cPeLoadRefNew:
Control(cPeInspector, cPeSpawnInsp, (Ref*)data);
break;
}
EtPeTool::Control(id, what, data);
break;
}
}
void PeInspector::DoInspect(Object *op)
{
if (!ObjectTable::PtrIsValid(op))
ShowAlert(eAlertNote, "instance 0x%x disappeard", op);
else if (strcmp(op->ClassName(), "InspectorItem") == 0) // hack
ShowAlert(eAlertNote, "would crash the inspector");
else
Push(new Ref(*op));
}
void PeInspector::ResetReferences()
{
referenceItems= new OrdCollection(10);
refTitle->SetString("References", TRUE);
references->SetCollection(referenceItems, TRUE);
}
void PeInspector::ResetObjects()
{
objTitle->SetString("Number of instances", TRUE);
objectItems= new ObjList();
objects->SetCollection(objectItems, TRUE);
}
void PeInspector::Reset()
{
objects->ClearSelection();
classes->ClearSelection();
}
void PeInspector::References(Object *op)
{
referenceItems= new OrdCollection(10);
refTitle->SetString(form("References to 0x%x (%s)", (int)op, op->ClassName()), TRUE);
findReferences->ReferencesTo(op);
{
ObjectTableIter next(0);
while (currentOp= next()) {
findReferences->ForObject(currentOp);
currentOp->IsA()->EnumerateMembers(findReferences);
}
}
references->SetCollection(referenceItems, TRUE);
}
void PeInspector::FoundReference(Object *op, char *name, int index)
{
char *cp;
if (index == -1)
cp= form("%s.%s", op->ClassName(), name);
else
cp= form("%s.%s[%d]", op->ClassName(), name, index);
referenceItems->Add(new PeObjectItem(cp, op));
}
Command *PeInspector::DoMenuCommand(int cmd)
{
Object *insp= objView->GetInspected()->GetObject();
switch (cmd) {
case cSHOWALL:
ShowAllInstances();
break;
case cUPDATELIST:
classes->LoadClasses();
ResetObjects();
break;
case cEMPTYCLASSES:
classes->ToggleHideEmpty();
ResetObjects();
break;
case cOBJREFERENCES:
References(insp);
break;
case cPRINT:
objView->Print();
break;
case cSPAWN:
Control(cPeInspector, cPeSpawnInsp, objView->GetInspected());
break;
case cEDITDECL:
case cEDITIMPL:
insp->EditSource(cmd == cEDITDECL);
break;
case cOBJBROWSER:
Control(cPeInspector, cPeShowOBrowser, insp);
break;
default:
return EtPeTool::DoMenuCommand(cmd);
}
return gNoChanges;
}
void PeInspector::ShowAllInstances()
{
Class *cl= classes->SelectedClass();
if (cl != 0)
LoadObjectsOfClass(cl, FALSE);
}
void PeInspector::DoSetupMenu(Menu *menu)
{
EtPeTool::DoSetupMenu(menu);
Class *cl= classes->SelectedClass();
if (cl) {
menu->EnableItems(cSHOWALL, cEDITDECL, cEDITIMPL, 0);
menu->ReplaceItem(cEDITDECL, form("Edit Definition of \"%s\"", cl->Name()));
menu->ReplaceItem(cEDITIMPL, form("Edit Implementation of \"%s\"", cl->Name()));
}
menu->ToggleItem(cEMPTYCLASSES, classes->HideEmptyClasses(),
"Show All Classes", "Hide Classes with no Instances");
menu->EnableItems(cUPDATELIST, cEMPTYCLASSES, cPRINT, 0);
}
void PeInspector::FreedMemory(void *addr, void *end)
{
Ref *r= objView->GetInspected();
u_int base;
if (r) {
base= (u_int)r->Addr();
if (base >= (u_int)addr && base < (u_int)end)
objView->InspectedDied();
}
if (path->Size() == 0)
return;
for (int i= 0; i < path->Size(); i++) {
r= (Ref*)path->At(i);
base= (u_int)r->Addr();
if (base >= (u_int)addr && base < (u_int)end)
RemoveDeletedRef(i, r);
}
}
void PeInspector::RemoveDeletedRef(int i, Ref *r)
{
if (i <= position)
position= Math::Max(0, position -1);
path->RemovePtr(r);
UpdateButtons();
}
void PeInspector::Spawn(Manager *m, Ref *ref, bool)
{
PeInspector *ip= new PeInspector(m);
ip->SetOnDismiss(eMgrClose);
ip->Show();
ip->Push(ref);
}
void PeInspector::ShowObject(Manager *m, Object *op, bool)
{
if (inspector == 0)
inspector= new PeInspector(m);
inspector->Show();
inspector->Push(new Ref(*op));
}